<?php

/**
 * Pwiff - PHP SWF Library
 *
 * LICENSE
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 *
 * @package    Pwiff
 * @subpackage Records
 * @copyright  Copyright (c) 2010 Steven Harris
 * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
 * @version    $Id: Shape.php 8 2010-02-22 04:06:23Z indigo.sunrise $
 */

/**
 * Shape record. Only used with DefineFont, as it contains no style info.
 *
 * @package    Pwiff
 * @subpackage Records
 */
class Pwiff_Record_Shape extends Pwiff_Record
{
	/**
	 * DefineShape version this record is being used with.
	 * 
	 * @var int
	 */
	protected $shapeVersion = 1;
	
	/**
	 * List of shape records.
	 *
	 * @var array
	 */
	protected $records = array();
	
	/**
	 * Sets the DefineShape version.
	 * 
	 * @param  int $version
	 * @return Pwiff_Record_Shape
	 */
	public function setShapeVersion($version)
	{
		$this->shapeVersion = $version;
		return $this;
	}
	
	/**
	 * Sets the list of shape records.
	 * 
	 * @param  array $records
	 * @return Pwiff_Record_Shape
	 */
	public function setShapeRecords(array $records)
	{
		$this->records = array();
		foreach ($records AS $record) {
			$this->addShapeRecord($record);
		}
		
		return $this;
	}
	
	/**
	 * Adds a shape record to the shape.
	 * 
	 * @param  Pwiff_Record_Shape_Record $record
	 * @return Pwiff_Record_Shape
	 */
	public function addShapeRecord(Pwiff_Record_Shape_Record $record)
	{
		if ($record->getParentShape() === null) {
			$record->setParentShape($this);
		}
		
		$this->records[] = $record;
		return $this;
	}
	
	/**
	 * Gets the DefineShape version.
	 * 
	 * @return int
	 */
	public function getShapeVersion()
	{
		return $this->shapeVersion;
	}
	
	/**
	 * Gets the list of shape records.
	 * 
	 * @return array
	 */
	public function getShapeRecords()
	{
		return $this->records;
	}
	
	/**
	 * Gets the number of fill bits.
	 * 
	 * @return int
	 */
	public function getFillBits()
	{
		return 0;
	}
	
	/**
	 * Gets the number of line bits.
	 * 
	 * @return int
	 */
	public function getLineBits()
	{
		return 0;
	}
	
	/**
	 * Gets the length of the record.
	 *
	 * @return int
	 */
	public function getRecordLength()
	{
		$length = 1; // UB[4] + UB[4]
		
		$fillBits = $this->getFillBits();
		$lineBits = $this->getLineBits();
		
		// iterate through each shape record
		foreach ($this->records AS $record)
		{
			$recordLen = 0;
			
			// we need to do extra work if it's a style change shape record
			if ($record instanceof Pwiff_Record_Shape_StyleChange)
			{
				// update the current number of fill/line bits if we changed
				// the style arrays
				if ($record->getNewFillStyles() !== null) {
					$fillBits = $record->getFillBits();
				}
				if ($record->getNewLineStyles() !== null) {
					$lineBits = $record->getLineBits();
				}
				
				$recordLen = $this->getStyleChangeLength($record, $fillBits, $lineBits);
			}
			else
			{
				$recordLen = $record->getRecordLength();
			}
			
			$length += $recordLen;
		}
		
		return $length;
	}
	
	/**
	 * Writes the Shape record to the given output instance.
	 * 
	 * @param  Pwiff_Output $out
	 */
	public function write(Pwiff_Output $out)
	{
		$out->byteAlign();
		$out->writeBits(0, 4);
		$out->writeBits(0, 4);
		
		foreach ($this->records AS $record) {
			$record->write($out);
		}
	}
	
	/**
	 * Gets the length of a style change shape record.
	 *
	 * @param  Pwiff_Record_Shape_StyleChange $record
	 * @param  int $fillBits
	 * @param  int $lineBits
	 * @return int
	 */
	protected function getStyleChangeLength(Pwiff_Record_Shape_StyleChange $record,
		$fillBits, $lineBits)
	{
		$bits = 6;
		
		// add move bits
		if ($record->getMoveDeltaX() !== 0 OR $record->getMoveDeltaY() !== 0) {
			$bits += 5;
			$bits += $record->getMoveBits() * 2;
		}
		
		// add fill bits
		if ($record->getFillStyle0() !== 0) {
			$bits += $fillBits;
		}
		if ($record->getFillStyle1() !== 0) {
			$bits += $fillBits;
		}
		
		// add line bits
		if ($record->getLineStyle() !== 0) {
			$bits += $lineBits;
		}
		
		// handle the case that new styles are set
		if ($record->getNewFillStyles() !== null OR $record->getNewLineStyles() !== null)
		{
			// FillStyleArray. We have to pad the bits to the next byte.
			if ($bits % 8 !== 0) {
				$bits += 8 - ($bits % 8);
			}
			$bits += 8 * $record->getNewFillStyles()->getRecordLength();
			
			// LineStyleArray (we add by a multiple of 8 last step, so byte aligning is not needed)
			$bits += 8 * $record->getNewLineStyles()->getRecordLength();
			
			// add the next two UB[4]
			$bits += 8;
		}
		
		return ceil($bits / 8);
	}
}
